﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System.Windows.Input;
using System.Windows;
using System.Windows.Controls.Primitives;
using Xceed.Silverlight.Data;
using System.Diagnostics;

namespace Xceed.Silverlight.DataGrid
{
  #region Metadata

  [TemplatePart( Name = "ColumnResizingThumb", Type = typeof( Thumb ) )]

  [TemplateVisualState( GroupName = "CommonStates", Name = "Pressed" )]

  [TemplateVisualState( GroupName = "ColumnVisibilityStates", Name = "Scrolling" )]
  [TemplateVisualState( GroupName = "ColumnVisibilityStates", Name = "Fixed" )]

  [TemplateVisualState( GroupName = "SortStates", Name = "Ascending" )]
  [TemplateVisualState( GroupName = "SortStates", Name = "Descending" )]
  [TemplateVisualState( GroupName = "SortStates", Name = "None" )]

  [TemplateVisualState( GroupName = "FixedColumnToggleButtonVisibilityStates", Name = "FixedColumnToggleButtonHidden" )]
  [TemplateVisualState( GroupName = "FixedColumnToggleButtonVisibilityStates", Name = "FixedColumnToggleButtonVisible" )]

  #endregion

  public class ColumnManagerCell : Cell
  {
    internal const int MinimumColumnWidth = 6;

    internal static readonly string FixedColumnToggleButtonVisible = "FixedColumnToggleButtonVisible";
    internal static readonly string FixedColumnToggleButtonHidden = "FixedColumnToggleButtonHidden";
    internal static readonly string FixedColumnToggleButtonStateScrolling = "Scrolling";
    internal static readonly string FixedColumnToggleButtonStateFixed = "Fixed";
    internal static readonly string SortingStateNone = "None";
    internal static readonly string SortingStateAscending = "Ascending";
    internal static readonly string SortingStateDescending = "Descending";

    internal static readonly XceedRoutedEvent OnColumnManagerCellIsPressedChangedEvent = new XceedRoutedEvent();
    internal static readonly XceedRoutedEvent ColumnManagerCellMouseLeftButtonDownEvent = new XceedRoutedEvent();
    internal static readonly XceedRoutedEvent ColumnManagerCellMouseLeftButtonUpEvent = new XceedRoutedEvent();
    internal static readonly XceedRoutedEvent OnColumnResizingThumbDragEvent = new XceedRoutedEvent();

    public ColumnManagerCell()
    {
      this.DefaultStyleKey = typeof( ColumnManagerCell );
    }

    #region IsPressed Property

    public bool IsPressed
    {
      get
      {
        return m_isPressed;
      }
      internal set
      {
        if( value != m_isPressed )
        {
          m_isPressed = value;

          this.EventManager.RaiseEvent( ColumnManagerCell.OnColumnManagerCellIsPressedChangedEvent, new XceedRoutedEventArgs( this ) );
        }
      }
    }

    private bool m_isPressed;

    #endregion

    #region ToggleParentColumnIsFixedCommand Property

    internal static readonly DependencyProperty ToggleParentColumnIsFixedCommandProperty = DependencyProperty.Register(
      "ToggleParentColumnIsFixedCommand",
      typeof( ICommand ),
      typeof( ColumnManagerCell ),
      new PropertyMetadata( null ) );

    public ICommand ToggleParentColumnIsFixedCommand
    {
      get
      {
        return ( ICommand )this.GetValue( ColumnManagerCell.ToggleParentColumnIsFixedCommandProperty );
      }
      internal set
      {
        this.SetValue( ColumnManagerCell.ToggleParentColumnIsFixedCommandProperty, value );
      }
    }

    #endregion // ToggleParentColumnIsFixedCommand Property

    // used by ColumnManagerRow for FixedColumnToggleButton
    internal bool IsMouseOver
    {
      get;
      private set;
    }

    public override void OnApplyTemplate()
    {
      base.OnApplyTemplate();

      Thumb columnResizerThumb = this.GetTemplateChild( "ColumnResizingThumb" ) as Thumb;

      if( columnResizerThumb != m_columnResizingThumb )
      {
        if( m_columnResizingThumb != null )
        {
          m_columnResizingThumb.DragStarted -= this.OnColumnResizingThumbDragStarted;
          m_columnResizingThumb.DragDelta -= this.OnColumnResizingThumbDragDelta;
          m_columnResizingThumb.DragCompleted -= this.OnColumnResizingThumbDragCompleted;
        }

        m_columnResizingThumb = columnResizerThumb;

        if( m_columnResizingThumb != null )
        {
          m_columnResizingThumb.DragStarted += this.OnColumnResizingThumbDragStarted;
          m_columnResizingThumb.DragDelta += this.OnColumnResizingThumbDragDelta;
          m_columnResizingThumb.DragCompleted += this.OnColumnResizingThumbDragCompleted;
        }
      }
    }

    protected override void OnMouseEnter( MouseEventArgs e )
    {
      this.IsMouseOver = true;
      base.OnMouseEnter( e );
    }

    protected override void OnMouseLeave( MouseEventArgs e )
    {
      this.IsMouseOver = false;
      base.OnMouseLeave( e );
    }

    protected override void OnMouseLeftButtonDown( MouseButtonEventArgs e )
    {
      XceedEventUtils.RaiseMouseButtonEvent( this, e, ColumnManagerCell.ColumnManagerCellMouseLeftButtonDownEvent );
    }

    protected override void OnMouseLeftButtonUp( MouseButtonEventArgs e )
    {
      XceedEventUtils.RaiseMouseButtonEvent( this, e, ColumnManagerCell.ColumnManagerCellMouseLeftButtonUpEvent );
    }

    internal override void SetFixedColumnToggleButtonVisibleState( string state, bool useTransitions )
    {
      this.VisualStateHelper.GoToFixedColumnToggleButtonVisibleState( state, useTransitions );
    }

    internal override void OnColumnIsDragPausedChanged()
    {
      // We do not want to hide the dragged ContentPresenter, 
      // which is what the base implementation do.
    }

    internal void SetSortingState( SortDirection direction, bool useTransitions )
    {
      string state;
      switch( direction )
      {
        case SortDirection.Ascending:
          state = ColumnManagerCell.SortingStateAscending;
          break;
        case SortDirection.Descending:
          state = ColumnManagerCell.SortingStateDescending;
          break;
        default:
          Debug.Assert( direction == SortDirection.None );
          state = ColumnManagerCell.SortingStateNone;
          break;
      }

      this.VisualStateHelper.GoToSortingState( state, useTransitions );
    }

    internal void SetFixedColumnToggleButtonState( string state, bool useTransitions )
    {
      this.VisualStateHelper.GoToFixedColumnToggleButtonState( state, useTransitions );
    }

    internal void SetHitTestVisible( bool allowResize )
    {
      if( m_columnResizingThumb == null )
        return;

      m_columnResizingThumb.IsHitTestVisible = allowResize;
    }

    internal bool IsColumnNegativeResizingThumb( double horizontalChange )
    {
      // The column is being resized but was previously resized too small; therefore, we need to go back to original size
      // 'this.ColumnNegativeResizingThumbDragDelta == 0' before starting to grow.
      // or 
      // User in resizing the column to be smaller; increment this.ColumnNegativeResizingThumbDragDelta 
      if( ( ( horizontalChange > 0 ) && ( m_columnNegativeResizingThumbDragDelta < 0 ) ) || ( horizontalChange <= 0 ) )
      {
        m_columnNegativeResizingThumbDragDelta += horizontalChange;    //add delta to member variable
        return true;
      }
      return false;
    }

    private void OnColumnResizingThumbDragStarted( object sender, DragStartedEventArgs e )
    {
    }

    private void OnColumnResizingThumbDragDelta( object sender, DragDeltaEventArgs e )
    {
      this.EventManager.RaiseEvent( ColumnManagerCell.OnColumnResizingThumbDragEvent, new XceedRoutedEventThumbDragDeltaArgs( this, e ) );
    }

    private void OnColumnResizingThumbDragCompleted( object sender, DragCompletedEventArgs e )
    {
      m_columnNegativeResizingThumbDragDelta = 0;
    }

    private Thumb m_columnResizingThumb;
    private double m_columnNegativeResizingThumbDragDelta;
  }
}
